package com.jiaomatech.tencent.cos.resource;

import com.qcloud.cos.COSClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.ProtocolResolver;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;

/**
 * Description: 定制 cos 协议 .<br>
 * - 通过 BeanFactoryPostProcessor 可以拿到Bean Factory.
 * - 通过 ProtocolResolver 定制协议的策略.
 * - 通过 ResourceLoaderAware 获取ResourceLoader的一个引用，便能够通过它获得各种资源
 *
 * @author jm
 */
public class CosStorageProtocolResolver
    implements BeanFactoryPostProcessor, ProtocolResolver, ResourceLoaderAware {

    public static final String PROTOCOL = "cos://";

    private static final Logger logger = LoggerFactory
        .getLogger(CosStorageProtocolResolver.class);

    private ConfigurableListableBeanFactory beanFactory;

    private COSClient cos;

    /**
     * 拿到 cos 连接.
     *
     * @return
     */
    private COSClient getCOS() {
        if (this.cos == null) {
            if (this.beanFactory.getBeansOfType(COSClient.class).size() > 1) {
                logger.warn("配置了多个cos的实现Bean，建议只配置一个.");
            }
            this.cos = this.beanFactory.getBean(COSClient.class);
        }
        return this.cos;
    }

    /**
     * 拿到 ConfigurableListableBeanFactory.
     *
     * @param beanFactory
     * @throws BeansException
     */
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
        throws BeansException {
        this.beanFactory = beanFactory;
    }

    /**
     * 定义资源策略.
     *
     * @param location       路由.
     * @param resourceLoader 资源加载.
     * @return 资源
     */
    @Override
    public Resource resolve(String location, ResourceLoader resourceLoader) {
        if (!location.startsWith(PROTOCOL)) {
            return null;
        }
        return new CosStorageResource(getCOS(), location);
    }

    /**
     * 给 Application Context 增加一个 ProtocolResolver.
     *
     * @param resourceLoader
     */
    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        if (DefaultResourceLoader.class.isAssignableFrom(resourceLoader.getClass())) {
            ((DefaultResourceLoader) resourceLoader).addProtocolResolver(this);
        } else {
            logger.warn("非实现 DefaultResourceLoader. cos:// 协议无法使用");
        }
    }
}
